"""
核心包管理接口和检测逻辑。
"""

import os
import platform
import subprocess
from abc import ABC, abstractmethod


class PackageManager(ABC):
    """所有包管理器的抽象基类。"""
    
    def __init__(self, sudo=False):
        """
        初始化包管理器。
        
        参数:
            sudo (bool): 是否使用sudo执行特权操作，默认为False
            示例: sudo=True
        """
        self.sudo = sudo
        self.name = self.__class__.__name__.replace('Manager', '').lower()
    
    def _run_command(self, command):
        """
        运行shell命令，可选择使用sudo。
        
        参数:
            command (list): 要执行的命令列表
            示例: command=["apt", "install", "curl"]
        
        返回:
            subprocess.CompletedProcess: 命令执行结果
        
        异常:
            RuntimeError: 命令执行失败时抛出
        """
        if self.sudo:
            command = ['sudo'] + command
        
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                check=False
            )
            return result
        except Exception as e:
            raise RuntimeError("Failed to execute command {0}: {1}".format(command, e))
    
    @abstractmethod
    def install(self, packages):
        """
        安装一个或多个软件包。
        
        参数:
            packages (str|list): 要安装的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 安装成功返回True，失败返回False
        """
        pass
    
    @abstractmethod
    def remove(self, packages):
        """
        移除一个或多个软件包。
        
        参数:
            packages (str|list): 要移除的软件包名称或列表
            示例: packages="curl" 或 packages=["curl", "wget"]
        
        返回:
            bool: 移除成功返回True，失败返回False
        """
        pass
    
    @abstractmethod
    def update(self):
        """
        更新软件包列表。
        
        返回:
            bool: 更新成功返回True，失败返回False
        """
        pass
    
    @abstractmethod
    def upgrade(self, packages=None):
        """
        升级软件包。
        
        参数:
            packages (str|list|None): 要升级的软件包名称或列表，None表示升级所有包
            示例: packages="curl" 或 packages=["curl", "wget"] 或 packages=None
        
        返回:
            bool: 升级成功返回True，失败返回False
        """
        pass
    
    @abstractmethod
    def search(self, pattern):
        """
        搜索软件包。
        
        参数:
            pattern (str): 搜索模式
            示例: pattern="python"
        
        返回:
            list: 包含匹配软件包信息的字典列表
        """
        pass
    
    @abstractmethod
    def info(self, package):
        """
        获取软件包信息。
        
        参数:
            package (str): 软件包名称
            示例: package="python3"
        
        返回:
            dict|None: 软件包信息字典，如果包不存在返回None
        """
        pass
    
    @abstractmethod
    def list_installed(self):
        """
        列出已安装的软件包。
        
        返回:
            list: 包含已安装软件包信息的字典列表
        """
        pass
    
    def installed(self, package):
        """
        检查指定软件包是否已安装。
        
        参数:
            package (str): 要检查的软件包名称
            示例: package="python3"
        
        返回:
            bool: 如果包已安装返回True，否则返回False
        """
        installed_packages = self.list_installed()
        
        # 检查包是否在已安装列表中
        for pkg_info in installed_packages:
            if 'name' in pkg_info and pkg_info['name'] == package:
                return True
        
        return False
    
    @abstractmethod
    def is_available(self):
        """
        检查此包管理器是否在系统上可用。
        
        返回:
            bool: 如果包管理器可用返回True，否则返回False
        """
        pass


class OnlinePackageManager(PackageManager):
    """在线包管理器的基类（apt、yum、dnf、apk）。"""
    
    def __init__(self, sudo=False):
        """
        初始化在线包管理器。
        
        参数:
            sudo (bool): 是否使用sudo执行特权操作，默认为False
            示例: sudo=True
        """
        super().__init__(sudo)
    
    @abstractmethod
    def clean_cache(self):
        """
        清理包缓存。
        
        返回:
            bool: 清理成功返回True，失败返回False
        """
        pass


class OfflinePackageManager(PackageManager):
    """离线包管理器的基类（dpkg、rpm）。"""
    
    def __init__(self, sudo=False):
        """
        初始化离线包管理器。
        
        参数:
            sudo (bool): 是否使用sudo执行特权操作，默认为False
            示例: sudo=True
        """
        super().__init__(sudo)
    
    @abstractmethod
    def verify(self, package):
        """
        验证软件包完整性。
        
        参数:
            package (str): 要验证的软件包名称
            示例: package="python3"
        
        返回:
            bool: 验证成功返回True，失败返回False
        """
        pass
    
    @abstractmethod
    def install_from_file(self, file_path):
        """
        从本地文件安装软件包。
        
        参数:
            file_path (str): 软件包文件路径
            示例: file_path="/tmp/python3.deb"
        
        返回:
            bool: 安装成功返回True，失败返回False
        """
        pass


def detect_package_manager():
    """
    自动检测当前系统适合的包管理器（包括在线和离线）。
    
    返回:
        PackageManager实例，如果没有找到合适的包管理器返回None
    """
    # 优先检测在线包管理器
    online_manager = detect_online_package_manager()
    if online_manager:
        return online_manager
    
    # 如果没有在线包管理器，检测离线包管理器
    offline_manager = detect_offline_package_manager()
    if offline_manager:
        return offline_manager
    
    return None


def detect_online_package_manager():
    """
    自动检测当前系统适合的在线包管理器。
    
    返回:
        OnlinePackageManager实例，如果没有找到合适的在线包管理器返回None
    """
    # 检查系统类型
    system = platform.system().lower()
    if system != 'linux':
        return None
    
    # 按优先级顺序检查在线包管理器
    managers_to_try = [
        ('apt', 'AptManager'),
        ('dnf', 'DnfManager'),
        ('yum', 'YumManager'),
        ('pacman', 'PacmanManager'),
        ('zypper', 'ZypperManager'),
        ('apk', 'ApkManager')
    ]
    
    for cmd, manager_class in managers_to_try:
        try:
            # 检查命令是否存在
            result = subprocess.run(
                ['which', cmd], 
                capture_output=True, 
                text=True
            )
            if result.returncode == 0:
                # 导入并实例化管理器
                from .online import AptManager, DnfManager, YumManager, PacmanManager, ZypperManager, ApkManager
                
                manager_classes = {
                    'AptManager': AptManager,
                    'DnfManager': DnfManager,
                    'YumManager': YumManager,
                    'PacmanManager': PacmanManager,
                    'ZypperManager': ZypperManager,
                    'ApkManager': ApkManager
                }
                
                if manager_class in manager_classes:
                    manager = manager_classes[manager_class]()
                    if manager.is_available():
                        return manager
        except:
            continue
    
    return None


def detect_offline_package_manager():
    """
    自动检测当前系统适合的离线包管理器。
    
    返回:
        OfflinePackageManager实例，如果没有找到合适的离线包管理器返回None
    """
    # 检查系统类型
    system = platform.system().lower()
    if system != 'linux':
        return None
    
    # 按优先级顺序检查离线包管理器
    managers_to_try = [
        ('dpkg', 'DpkgManager'),
        ('rpm', 'RpmManager')
    ]
    
    for cmd, manager_class in managers_to_try:
        try:
            # 检查命令是否存在
            result = subprocess.run(
                ['which', cmd], 
                capture_output=True, 
                text=True
            )
            if result.returncode == 0:
                # 导入并实例化管理器
                from .offline import DpkgManager, RpmManager
                
                manager_classes = {
                    'DpkgManager': DpkgManager,
                    'RpmManager': RpmManager
                }
                
                if manager_class in manager_classes:
                    manager = manager_classes[manager_class]()
                    if manager.is_available():
                        return manager
        except:
            continue
    
    return None